/**
 * Copyright (c) 2006-2015, JGraph Ltd
 * Copyright (c) 2006-2015, Gaudenz Alder
 */
mxCodecRegistry.register(function () {
  /**
	 * Class: mxEditorCodec
	 *
	 * Codec for <mxEditor>s. This class is created and registered
	 * dynamically at load time and used implicitely via <mxCodec>
	 * and the <mxCodecRegistry>.
	 *
	 * Transient Fields:
	 *
	 * - modified
	 * - lastSnapshot
	 * - ignoredChanges
	 * - undoManager
	 * - graphContainer
	 * - toolbarContainer
	 */
  var codec = new mxObjectCodec(new mxEditor(),
    ['modified', 'lastSnapshot', 'ignoredChanges',
      'undoManager', 'graphContainer', 'toolbarContainer'])

  /**
	 * Function: beforeDecode
	 *
	 * Decodes the ui-part of the configuration node by reading
	 * a sequence of the following child nodes and attributes
	 * and passes the control to the default decoding mechanism:
	 *
	 * Child Nodes:
	 *
	 * stylesheet - Adds a CSS stylesheet to the document.
	 * resource - Adds the basename of a resource bundle.
	 * add - Creates or configures a known UI element.
	 *
	 * These elements may appear in any order given that the
	 * graph UI element is added before the toolbar element
	 * (see Known Keys).
	 *
	 * Attributes:
	 *
	 * as - Key for the UI element (see below).
	 * element - ID for the element in the document.
	 * style - CSS style to be used for the element or window.
	 * x - X coordinate for the new window.
	 * y - Y coordinate for the new window.
	 * width - Width for the new window.
	 * height - Optional height for the new window.
	 * name - Name of the stylesheet (absolute/relative URL).
	 * basename - Basename of the resource bundle (see <mxResources>).
	 *
	 * The x, y, width and height attributes are used to create a new
	 * <mxWindow> if the element attribute is not specified in an add
	 * node. The name and basename are only used in the stylesheet and
	 * resource nodes, respectively.
	 *
	 * Known Keys:
	 *
	 * graph - Main graph element (see <mxEditor.setGraphContainer>).
	 * title - Title element (see <mxEditor.setTitleContainer>).
	 * toolbar - Toolbar element (see <mxEditor.setToolbarContainer>).
	 * status - Status bar element (see <mxEditor.setStatusContainer>).
	 *
	 * Example:
	 *
	 * (code)
	 * <ui>
	 *   <stylesheet name="css/process.css"/>
	 *   <resource basename="resources/app"/>
	 *   <add as="graph" element="graph"
	 *     style="left:70px;right:20px;top:20px;bottom:40px"/>
	 *   <add as="status" element="status"/>
	 *   <add as="toolbar" x="10" y="20" width="54"/>
	 * </ui>
	 * (end)
	 */
  codec.afterDecode = function (dec, node, obj) {
    // Assigns the specified templates for edges
    var defaultEdge = node.getAttribute('defaultEdge')

    if (defaultEdge != null) {
      node.removeAttribute('defaultEdge')
      obj.defaultEdge = obj.templates[defaultEdge]
    }

    // Assigns the specified templates for groups
    var defaultGroup = node.getAttribute('defaultGroup')

    if (defaultGroup != null) {
      node.removeAttribute('defaultGroup')
      obj.defaultGroup = obj.templates[defaultGroup]
    }

    return obj
  }

  /**
	 * Function: decodeChild
	 *
	 * Overrides decode child to handle special child nodes.
	 */
  codec.decodeChild = function (dec, child, obj) {
    if (child.nodeName == 'Array') {
      var role = child.getAttribute('as')

      if (role == 'templates') {
        this.decodeTemplates(dec, child, obj)
        return
      }
    } else if (child.nodeName == 'ui') {
      this.decodeUi(dec, child, obj)
      return
    }

    mxObjectCodec.prototype.decodeChild.apply(this, arguments)
  }

  /**
	 * Function: decodeTemplates
	 *
	 * Decodes the cells from the given node as templates.
	 */
  codec.decodeUi = function (dec, node, editor) {
    var tmp = node.firstChild
    while (tmp != null) {
      if (tmp.nodeName == 'add') {
        var as = tmp.getAttribute('as')
        var elt = tmp.getAttribute('element')
        var style = tmp.getAttribute('style')
        var element = null

        if (elt != null) {
          element = document.getElementById(elt)

          if (element != null && style != null) {
            element.style.cssText += ';' + style
          }
        } else {
          var x = parseInt(tmp.getAttribute('x'))
          var y = parseInt(tmp.getAttribute('y'))
          var width = tmp.getAttribute('width')
          var height = tmp.getAttribute('height')

          // Creates a new window around the element
          element = document.createElement('div')
          element.style.cssText = style

          var wnd = new mxWindow(mxResources.get(as) || as,
            element, x, y, width, height, false, true)
          wnd.setVisible(true)
        }

        // TODO: Make more generic
        if (as == 'graph') {
          editor.setGraphContainer(element)
        } else if (as == 'toolbar') {
          editor.setToolbarContainer(element)
        } else if (as == 'title') {
          editor.setTitleContainer(element)
        } else if (as == 'status') {
          editor.setStatusContainer(element)
        } else if (as == 'map') {
          editor.setMapContainer(element)
        }
      } else if (tmp.nodeName == 'resource') {
        mxResources.add(tmp.getAttribute('basename'))
      } else if (tmp.nodeName == 'stylesheet') {
        mxClient.link('stylesheet', tmp.getAttribute('name'))
      }

      tmp = tmp.nextSibling
    }
  }

  /**
	 * Function: decodeTemplates
	 *
	 * Decodes the cells from the given node as templates.
	 */
  codec.decodeTemplates = function (dec, node, editor) {
    if (editor.templates == null) {
      editor.templates = []
    }

    var children = mxUtils.getChildNodes(node)
    for (var j = 0; j < children.length; j++) {
      var name = children[j].getAttribute('as')
      var child = children[j].firstChild

      while (child != null && child.nodeType != 1) {
        child = child.nextSibling
      }

      if (child != null) {
        // LATER: Only single cells means you need
        // to group multiple cells within another
        // cell. This should be changed to support
        // arrays of cells, or the wrapper must
        // be automatically handled in this class.
        editor.templates[name] = dec.decodeCell(child)
      }
    }
  }

  // Returns the codec into the registry
  return codec
}())
